#ifndef BASE_SHAREDEXCLUSIVELOCK_H_
#define BASE_SHAREDEXCLUSIVELOCK_H_

#include "constructormagic.h"
#include "criticalsection.h"
#include "event.h"

namespace base {

	// This class provides shared-exclusive lock. It can be used in cases like
	// multiple-readers/single-writer model.
	class SharedExclusiveLock
	{
	public:
		SharedExclusiveLock();

		// Locking/unlocking methods. It is encouraged to use SharedScope or
		// ExclusiveScope for protection.
		void LockExclusive();
		void UnlockExclusive();
		void LockShared();
		void UnlockShared();

	private:
		base::CriticalSection cs_exclusive_;
		base::CriticalSection cs_shared_;
		base::Event shared_count_is_zero_;
		int shared_count_;

		DISALLOW_COPY_AND_ASSIGN(SharedExclusiveLock);
	};

	class SharedScope {
	public:
		explicit SharedScope(SharedExclusiveLock* lock) : lock_(lock) {
			lock_->LockShared();
		}

		~SharedScope() {
			lock_->UnlockShared();
		}

	private:
		SharedExclusiveLock* lock_;

		DISALLOW_COPY_AND_ASSIGN(SharedScope);
	};

	class ExclusiveScope {
	public:
		explicit ExclusiveScope(SharedExclusiveLock* lock) : lock_(lock) {
			lock_->LockExclusive();
		}

		~ExclusiveScope() {
			lock_->UnlockExclusive();
		}

	private:
		SharedExclusiveLock* lock_;

		DISALLOW_COPY_AND_ASSIGN(ExclusiveScope);
	};

}  // namespace base

#endif  // BASE_SHAREDEXCLUSIVELOCK_H_
